﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Diplomova_prace
{
    class Derivation_alg
    {
        Expression v = new Expression();
        Derivace_ret ret = new Derivace_ret();
        public delegate void PostHandler();
        public event PostHandler post;
        bool incorrect = false;
        public Derivation_alg()
        {
            v.incorrectInput += v_incorrectInput;
        }

        void v_incorrectInput()
        {
            if (!incorrect)
                post();
            incorrect = true;
        }
        public Derivace_ret LinearDerivate(string function, double point, double step = 0.00001)
        {
            incorrect = false;
            double h = step;
            double f0 = v.ComputeRPN(v.RPN(function), point + h);
            double f1 = v.ComputeRPN(v.RPN(function), point);
            ret.hProperty = h;
            ret.f0Property = f0;
            ret.f1Property = f1;
            ret.xProperty = point;
            ret.Result = (f0 - f1) / h;
            return ret;
        }
        public Derivace_ret QudraticDerivate(string function, double point,double step=0.00001)
        {
            incorrect = false;
            double h = step;
            double f0 = v.ComputeRPN(v.RPN(function), point + h);
            double f1 = v.ComputeRPN(v.RPN(function), point-h);
            ret.hProperty = h;
            ret.f0Property = f0;
            ret.f1Property = f1;
            ret.xProperty = point;
            ret.Result = (f0 - f1) / (2*h);
            return ret;
        }
        public Derivace_ret QudraticSecondDerivate(string function, double point, double step = 0.00001)
        {
            incorrect = false;
            double h = step;
            double f2 = v.ComputeRPN(v.RPN(function), point - h);
            double f1 = v.ComputeRPN(v.RPN(function), point);
            double f0 = v.ComputeRPN(v.RPN(function), point + h);
            ret.hProperty = h;
            ret.f0Property = f0;
            ret.f1Property = f1;
            ret.f2Property = f2;
            ret.xProperty = point;
            ret.Result = (f2 - 2 * f1 + f0) / (h * h);
            return ret;
        }
        public Derivace_ret RichardsonovaExtrapolace(string function, double point,double presnost, double step = 0.8)
        {
             incorrect = false;
             double[,] matrix = new double[30, 30];
             for (int i = 0; i < matrix.GetLength(0); i++)
             {
                 matrix[i, 0] = (QudraticDerivate(function, point, Math.Pow(step,i+1)).Result);
                 for (int j = 1; j <= i; j++)
                 {
                     matrix[i, j] =((Math.Pow(2, j+1) *(matrix[i, j-1]) - matrix[i - 1, j - 1]) / (Math.Pow(2, j+1) - 1));
                 }
                 if (i > 0)
                     if (Math.Abs(matrix[i, i] - matrix[i, i - 1]) < presnost)
                     {
                         ret.RichardsonProperty = Copy(matrix, i);
                         return ret;
                     }
             }
           ret.RichardsonProperty =  Copy(matrix, matrix.GetLength(0) - 1);
           return ret;
        }
        public double[,] Copy(double[,] matrixA, int size)
        {
            double[,] matrixB = new double[size + 1, size + 1];
            for (int i = 0; i <= size; i++)
            {
                for (int j = 0; j <= size; j++)
                {
                    matrixB[i, j] = matrixA[i, j];
                }
            }
            return matrixB;
        }
    }
    class Derivace_ret
    {
        double h;
        double f0;
        double f1;
        double f2;
        double result;
        double x;
        double[,] Richardson = new double[30,30];
        public double hProperty
        {
            get { return h; }
            set { h = value; }
        }
        public double f0Property
        {
            get { return f0; }
            set { f0 = value; }
        }
        public double f1Property
        {
            get { return f1; }
            set { f1 = value; }
        }
        public double f2Property
        {
            get { return f2; }
            set { f2 = value; }
        }
        public double xProperty
        {
            get { return x; }
            set { x = value; }
        }
        public double[,] RichardsonProperty
        {
            get { return Richardson; }
            set { Richardson = value; }
        }
        public double Result
        {
            get { return result; }
            set { result = value; }
        }
    }
}
